package com.tensquare.user.service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import com.tensquare.user.util.UserConstant;
import com.tensquare.util.IdWorker;
import com.tensquare.util.JwtUtil;
import com.tensquare.util.NotNullHelps;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;


import com.tensquare.user.dao.UserDao;
import com.tensquare.user.model.User;

@Slf4j
@Service
public class UserService {

	@Autowired
	private UserDao userDao;
	
	@Autowired
	private IdWorker idWorker;

	@Autowired
	private BCryptPasswordEncoder encoder ;

	@Autowired
	private RabbitTemplate rabbitTemplate ;

	@Autowired
	private HttpServletRequest request ;

	@Autowired
	private JwtUtil jwtUtil ;

	@Autowired
	private RedisTemplate redisTemplate;

	private String redisValue ;

	private String redisKey ;

	private String message ;

	@Transactional
	public void deleteById(String id) {
//		this.oldJwtCheck(); // 旧版jwt验证 --> 新版[拦截器]
		String jwtToken = (String) request.getAttribute("claims_admin");
		if (NotNullHelps.isNotNull(jwtToken) == false) {
			throw new RuntimeException("异常--权限");
		} else {
			userDao.deleteById(id);
		}
	}

	private void oldJwtCheck() {
		String header = request.getHeader(UserConstant.request_header);
		if (NotNullHelps.isNotNull(header) == false) {
			throw new RuntimeException("权限不足");
		}
		if (header.startsWith(UserConstant.request_header_start) == false) {
			throw new RuntimeException("权限不足");
		}
		String jwtToken = header.substring(7);
		try {
			Claims claims = jwtUtil.parseJWT(jwtToken);
			String roles = (String) claims.get("roles");
			if ("admin".equals(roles) == false) {
				throw new RuntimeException("权限不足");
			}
		} catch (Exception e) {
			throw new RuntimeException("权限不足");
		}
	}

	public void update(User user) {
		userDao.save(user);
	}

	@Transactional
	public void updateFanAndFollowCount(Integer count, String userId, String friendId) {
		userDao.updateFollowCount(count, userId);
		userDao.updateFanCount(count, friendId);
	}

	public void saveUser(User user) {
		user.setId( idWorker.nextId().toString());
		user.setPassword(encoder.encode(user.getPassword()));
		user.setRegdate(new Date());//注册日期
		user.setUpdatedate(new Date());
		user.setFollowcount(0);//关注数
		user.setFanscount(0);//粉丝数
		user.setOnline(0L);//在线时长
		userDao.save(user);
	}

	private Specification<User> createSpecification(Map searchMap) {
		return new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicateList = new ArrayList<Predicate>();
				// ID
				if (searchMap.get("id")!=null && !"".equals(searchMap.get("id"))) {
					predicateList.add(cb.like(root.get("id").as(String.class), "%"+(String)searchMap.get("id")+"%"));
				}
				// 手机号码
				if (searchMap.get("mobile")!=null && !"".equals(searchMap.get("mobile"))) {
					predicateList.add(cb.like(root.get("mobile").as(String.class), "%"+(String)searchMap.get("mobile")+"%"));
				}
				// 密码
				if (searchMap.get("password")!=null && !"".equals(searchMap.get("password"))) {
					predicateList.add(cb.like(root.get("password").as(String.class), "%"+(String)searchMap.get("password")+"%"));
				}
				// 昵称
				if (searchMap.get("nickname")!=null && !"".equals(searchMap.get("nickname"))) {
					predicateList.add(cb.like(root.get("nickname").as(String.class), "%"+(String)searchMap.get("nickname")+"%"));
				}
				// 性别
				if (searchMap.get("sex")!=null && !"".equals(searchMap.get("sex"))) {
					predicateList.add(cb.like(root.get("sex").as(String.class), "%"+(String)searchMap.get("sex")+"%"));
				}
				// 头像
				if (searchMap.get("avatar")!=null && !"".equals(searchMap.get("avatar"))) {
					predicateList.add(cb.like(root.get("avatar").as(String.class), "%"+(String)searchMap.get("avatar")+"%"));
				}
				// E-Mail
				if (searchMap.get("email")!=null && !"".equals(searchMap.get("email"))) {
					predicateList.add(cb.like(root.get("email").as(String.class), "%"+(String)searchMap.get("email")+"%"));
				}
				// 兴趣
				if (searchMap.get("interest")!=null && !"".equals(searchMap.get("interest"))) {
					predicateList.add(cb.like(root.get("interest").as(String.class), "%"+(String)searchMap.get("interest")+"%"));
				}
				// 个性
				if (searchMap.get("personality")!=null && !"".equals(searchMap.get("personality"))) {
					predicateList.add(cb.like(root.get("personality").as(String.class), "%"+(String)searchMap.get("personality")+"%"));
				}

				return cb.and( predicateList.toArray(new Predicate[predicateList.size()]));

			}
		};

	}


	public List<User> findAll() {
		return userDao.findAll();
	}

	public Page<User> findSearch(Map whereMap, int page, int size) {
		Specification<User> specification = createSpecification(whereMap);
		PageRequest pageRequest =  PageRequest.of(page-1, size);
		return userDao.findAll(specification, pageRequest);
	}

	public List<User> findSearch(Map whereMap) {
		Specification<User> specification = createSpecification(whereMap);
		return userDao.findAll(specification);
	}

	public User findById(String id) {
		return userDao.findById(id).get();
	}

	// 缓存  用户  控制台 各存储一份
	public void sendSMS(String mobile) {
		String checkCode = RandomStringUtils.randomNumeric(6);
		log.info(" ## 验证码 : " + checkCode+"\n\n");

		//	redis存储
		redisValue = checkCode;
		redisKey = UserConstant.redis_code_prefix + mobile;
		redisTemplate.opsForValue().set(redisKey, redisValue, 6, TimeUnit.HOURS);

//		Map<String, String> map = new HashMap<String, String>();
//		map.put("code", checkCode);
//		map.put("mobile", mobile);
//		String routingKey = "sms" ;
//		rabbitTemplate.convertAndSend(routingKey, map);

	}

	public User loginUser(User user) {
		User userData = userDao.findByMobile(user.getMobile());
		if (NotNullHelps.isNotNull(userData) == false) {
			message = "## 无此用户 @@";
		} else {
			String dataPassword = userData.getPassword();
			if (encoder.matches(user.getPassword(),dataPassword) == false) {
				message = "密码不对[user]";
				userData = null;
			} else {
				message = "$$密码验证无误@@";
			}
		}
		log.info(message);
		return userData;
	}
}
